open Unix
open Queue

exception FatalError

let mess ?(step=false) str = 
	print_string (str ^ "\n");
	Format.print_flush( );
	if step then ignore(read_line( )) 
	
let visualBuild = ref false
let startOnBuildEnd = ref false
let doAll = ref false
let exe_name = ref "abgps.exe" 

let arguments = [
	("-o", Arg.String (fun str ->   exe_name := str), "Executable name");
	("-visual" , Arg.Unit(fun ( ) -> visualBuild := true), "Build visual");
	("-start",  Arg.Unit(fun ( ) -> startOnBuildEnd := true), "Start on build");
	("-all" , Arg.Unit(fun ( ) -> doAll := true), "Build all")]

let _ = 
	Arg.parse arguments (fun _->( )) "usage:";
	mess (if !visualBuild then "\nBuilding " else "visual demo");
	
	let bv str = if !visualBuild then str else "" in
	let makefile = "Build//MakeData" ^ bv "Visual" ^ ".dat" in
	
	let builder_lst = 
	[("ocamlyacc",".mly");
	("ocamllex",".mll");
	("ocamlc -c -thread unix.cma threads.cma graphics.cma -I +lablgtk2 ",".mli");
	("ocamlc -c -thread unix.cma threads.cma graphics.cma -I +lablgtk2 ",".ml")] in

	let compile filename = 
		let builder = fst (List.find (fun (_,ext) -> Filename.check_suffix filename ext) builder_lst)
		in Sys.command (builder ^ " " ^ filename) in
	
	let file_modification = create( ) in
	let ic = open_in makefile in
	let rec inner ( )=
			try
				let data = input_line ic in
				let reg = Str.regexp "\\([a-z A-Z \\._]+\\)[,]\\([0-9]+\\)" in
				if Str.string_match reg data 0 then (
					let filename = Str.matched_group 1 data in
					let mod_time =  Str.matched_group 2 data in
					add (filename,(float_of_string mod_time)) file_modification; inner( ))
				else failwith ("Invalid data line: " ^ data)
			with _->( )	
	in inner ( )	;
	close_in ic; 
	
	let obj_queue = create( ) in
	let out_queue = create( ) in
	iter 
	(fun (filename , last_time) -> 
		if not (Sys.file_exists filename) then failwith (filename ^ " doesn't exists\n");
		let stats = stat filename in
		let m_time = stats.st_mtime in
		add (filename, m_time) out_queue;
		if Filename.check_suffix filename ".ml" 
			then add ((Filename.chop_extension filename) ^ ".cmo") obj_queue;
		if m_time > last_time or !doAll
		then (let ret_val = compile filename in
				if ret_val = 0 then mess ("=====Built " ^ filename ^ "=====")
				else exit ret_val ) 
		else  mess (filename ^ " nothing to do"))
	 file_modification;
	 
	 let oc = open_out makefile in
	 iter (fun (filename,last_time) ->
			output_string oc (filename ^ "," ^ string_of_float last_time ^ "\n"))
	 out_queue;
	 close_out oc;
	 let build_command = 
		"ocamlc   -thread -I +lablgtk2 lablgtk.cma " ^ 
		"str.cma unix.cma threads.cma graphics.cma gtkInit.cmo " in
	 
	 let args = fold (fun argsSoFar arg -> argsSoFar ^" "^arg) "" obj_queue in
	 if (Sys.command (build_command ^ args ^ " -o " ^ !exe_name) = 0) 
	 then (
		mess ("Built " ^ !exe_name);
		if !startOnBuildEnd then ignore(Sys.command (!exe_name)))
	 else mess "Final build failed"
	 
				
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		
		